From 7bbbb01ff521065c10d41185cc64f2823a5a6c9c Mon Sep 17 00:00:00 2001 From: Cosimo Cecchi Date: Mon, 22 Apr 2013 17:28:23 -0400 Subject: [PATCH] window: rework the CSD theming layer Instead of having three different boxes and style classes, we can just get away with the regular background box, plus a window-frame, which contains the external frame, together with the window drop shadows. GtkWindow now has special code to ensure the backing actual window is allocated big enough to accomodate the shadows (using the shadow size calculations introduced in the previous commit). We also use the margin value to determine the size of the invisible borders (which can then be different than the shadow). --- gtk/gtkwindow.c | 255 +++++++++++++++++++++++++----------------------- 1 file changed, 133 insertions(+), 122 deletions(-) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index c4086e7d2b..fe00a5c54d 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -35,6 +35,7 @@ #include "gtkwindowprivate.h" #include "gtkaccelgroupprivate.h" #include "gtkbindings.h" +#include "gtkcssshadowsvalueprivate.h" #include "gtkkeyhash.h" #include "gtkmain.h" #include "gtkmnemonichash.h" @@ -6067,68 +6068,65 @@ set_grip_position (GtkWindow *window) } static void -get_decoration_borders (GtkWidget *widget, - GtkBorder *window_border, - GtkBorder *outer_border) +sum_borders (GtkBorder *one, + GtkBorder *two) { + one->top += two->top; + one->right += two->right; + one->bottom += two->bottom; + one->left += two->left; +} + +static void +get_decoration_size (GtkWidget *widget, + GtkBorder *decorations) +{ + GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv; + GtkBorder border = { 0 }; + GtkBorder margin; GtkStyleContext *context; GtkStateFlags state; - GdkWindow *window; - gboolean maximized = FALSE; - const GtkBorder empty = { 0 }; - GtkBorder outer; + GtkCssValue *shadows; + + *decorations = border; + if (!priv->client_decorated) + return; + + if (gtk_window_get_maximized (GTK_WINDOW (widget))) + return; + + state = gtk_widget_get_state_flags (widget); context = gtk_widget_get_style_context (widget); - state = gtk_style_context_get_state (context); - window = gtk_widget_get_window (widget); - if (window != NULL) - maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED; - if (window_border != NULL) - { - if (maximized) - { - *window_border = empty; - } - else - { - gtk_style_context_save (context); - gtk_style_context_add_class (context, "window-border"); - gtk_style_context_get_border (context, state, window_border); - gtk_style_context_restore (context); - } - } + gtk_style_context_save (context); + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND); + gtk_style_context_add_class (context, "window-frame"); - if (window_border != NULL || outer_border != NULL) - { - if (maximized) - { - outer = empty; - } - else - { - gtk_style_context_save (context); - gtk_style_context_add_class (context, "window-outer-border"); - gtk_style_context_get_border (context, state, &outer); - gtk_style_context_restore (context); - } + /* Always sum border + padding */ + gtk_style_context_get_border (context, state, decorations); + gtk_style_context_get_padding (context, state, &border); + sum_borders (decorations, &border); - if (outer_border != NULL) - { - *outer_border = outer; - } - else - { - window_border->left += outer.left; - window_border->right += outer.right; - window_border->top += outer.top; - window_border->bottom += outer.bottom; - } - } + /* Calculate the size of the drop shadows ... */ + shadows = _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BOX_SHADOW); + _gtk_css_shadows_value_get_extents (shadows, &border); + + /* ... and compare it to the margin size, which we use for resize grips */ + gtk_style_context_get_margin (context, state, &margin); + + border.top = MAX (border.top, margin.top); + border.right = MAX (border.right, margin.right); + border.bottom = MAX (border.bottom, margin.bottom); + border.left = MAX (border.left, margin.left); + + sum_borders (decorations, &border); + + gtk_style_context_restore (context); } static void -update_border_windows (GtkWindow *window, GtkBorder *border) +update_border_windows (GtkWindow *window) { GtkWidget *widget = (GtkWidget *)window; GtkWindowPrivate *priv = window->priv; @@ -6137,10 +6135,20 @@ update_border_windows (GtkWindow *window, GtkBorder *border) cairo_region_t *region; cairo_rectangle_int_t rect; gint width, height; + GtkBorder border; + GtkStyleContext *context; if (priv->border_window[0] == NULL) return; + context = gtk_widget_get_style_context (widget); + gtk_style_context_save (context); + gtk_style_context_add_class (context, "window-frame"); + gtk_style_context_get_margin (context, + gtk_widget_get_state_flags (widget), + &border); + gtk_style_context_restore (context); + if (!priv->resizable || gtk_window_get_maximized (window)) { resize_h = resize_v = FALSE; @@ -6165,31 +6173,31 @@ update_border_windows (GtkWindow *window, GtkBorder *border) "decoration-resize-handle", &handle, NULL); - width = gtk_widget_get_allocated_width (widget) - (border->left + border->right); - height = gtk_widget_get_allocated_height (widget) - (border->top + border->bottom); + width = gtk_widget_get_allocated_width (widget) - (border.left + border.right); + height = gtk_widget_get_allocated_height (widget) - (border.top + border.bottom); if (resize_h && resize_v) { gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH_WEST], 0, 0, - border->left + handle, border->top + handle); + border.left + handle, border.top + handle); gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH_EAST], - border->left + width - handle, 0, - border->right + handle, border->top + handle); + border.left + width - handle, 0, + border.right + handle, border.top + handle); gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH_WEST], - 0, border->top + height - handle, - border->left + handle, border->bottom + handle); + 0, border.top + height - handle, + border.left + handle, border.bottom + handle); gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH_EAST], - border->left + width - handle, border->top + height - handle, - border->right + handle, border->bottom + handle); + border.left + width - handle, border.top + height - handle, + border.right + handle, border.bottom + handle); rect.x = 0; rect.y = 0; - rect.width = border->left + handle; - rect.height = border->top + handle; + rect.width = border.left + handle; + rect.height = border.top + handle; region = cairo_region_create_rectangle (&rect); - rect.x = border->left; - rect.y = border->top; + rect.x = border.left; + rect.y = border.top; rect.width = handle; rect.height = handle; cairo_region_subtract_rectangle (region, &rect); @@ -6199,11 +6207,11 @@ update_border_windows (GtkWindow *window, GtkBorder *border) rect.x = 0; rect.y = 0; - rect.width = border->right + handle; - rect.height = border->top + handle; + rect.width = border.right + handle; + rect.height = border.top + handle; region = cairo_region_create_rectangle (&rect); rect.x = 0; - rect.y = border->top; + rect.y = border.top; rect.width = handle; rect.height = handle; cairo_region_subtract_rectangle (region, &rect); @@ -6213,10 +6221,10 @@ update_border_windows (GtkWindow *window, GtkBorder *border) rect.x = 0; rect.y = 0; - rect.width = border->left + handle; - rect.height = border->bottom + handle; + rect.width = border.left + handle; + rect.height = border.bottom + handle; region = cairo_region_create_rectangle (&rect); - rect.x = border->left; + rect.x = border.left; rect.y = 0; rect.width = handle; rect.height = handle; @@ -6227,8 +6235,8 @@ update_border_windows (GtkWindow *window, GtkBorder *border) rect.x = 0; rect.y = 0; - rect.width = border->right + handle; - rect.height = border->bottom + handle; + rect.width = border.right + handle; + rect.height = border.bottom + handle; region = cairo_region_create_rectangle (&rect); rect.x = 0; rect.y = 0; @@ -6258,21 +6266,21 @@ update_border_windows (GtkWindow *window, GtkBorder *border) if (resize_h) { - x = border->left + handle; + x = border.left + handle; w = width - 2 * handle; } else { x = 0; - w = width + border->left + border->right; + w = width + border.left + border.right; } gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_NORTH], x, 0, - w, border->top); + w, border.top); gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_SOUTH], - x, border->top + height, - w, border->bottom); + x, border.top + height, + w, border.bottom); gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_NORTH]); gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_SOUTH]); @@ -6289,22 +6297,22 @@ update_border_windows (GtkWindow *window, GtkBorder *border) if (resize_v) { - y = border->top + handle; + y = border.top + handle; h = height - 2 * handle; } else { y = 0; - h = height + border->top + border->bottom; + h = height + border.top + border.bottom; } gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_WEST], 0, y, - border->left, h); + border.left, h); gdk_window_move_resize (priv->border_window[GDK_WINDOW_EDGE_EAST], - border->left + width, y, - border->right, h); + border.left + width, y, + border.right, h); gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_WEST]); gdk_window_show (priv->border_window[GDK_WINDOW_EDGE_EAST]); @@ -6352,7 +6360,7 @@ _gtk_window_set_allocation (GtkWindow *window, gtk_widget_set_allocation (widget, allocation); - get_decoration_borders (widget, &window_border, NULL); + get_decoration_size (widget, &window_border); border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); child_allocation.x = 0; @@ -6407,7 +6415,7 @@ _gtk_window_set_allocation (GtkWindow *window, { update_grip_visibility (window); set_grip_position (window); - update_border_windows (window, &window_border); + update_border_windows (window); } } @@ -6554,6 +6562,7 @@ gtk_window_style_updated (GtkWidget *widget) { GtkWindow *window = GTK_WINDOW (widget); GtkWindowPrivate *priv = window->priv; + GdkRGBA transparent = { 0.0, 0.0, 0.0, 0.0 }; GdkRectangle rect; GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget); @@ -6566,6 +6575,13 @@ gtk_window_style_updated (GtkWidget *widget) set_grip_shape (window); } + + if (gtk_widget_get_realized (widget)) + { + gdk_window_set_background_rgba (gtk_widget_get_window (widget), + &transparent); + gtk_widget_queue_resize (widget); + } } static void @@ -6783,12 +6799,10 @@ gtk_window_get_resize_grip_area (GtkWindow *window, g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - if (!window->priv->has_resize_grip) + if (!priv->has_resize_grip) return FALSE; - if (priv->client_decorated) - get_decoration_borders (widget, &window_border, NULL); - + get_decoration_size (widget, &window_border); gtk_widget_get_allocation (widget, &allocation); gtk_widget_style_get (widget, @@ -7449,7 +7463,7 @@ gtk_window_get_preferred_width (GtkWidget *widget, if (priv->decorated && !priv->fullscreen) { - get_decoration_borders (widget, &window_border, NULL); + get_decoration_size (widget, &window_border); if (priv->title_box != NULL) gtk_widget_get_preferred_width (priv->title_box, @@ -7498,7 +7512,7 @@ gtk_window_get_preferred_width_for_height (GtkWidget *widget, if (priv->decorated && !priv->fullscreen) { - get_decoration_borders (widget, &window_border, NULL); + get_decoration_size (widget, &window_border); if (priv->title_box != NULL) gtk_widget_get_preferred_width_for_height (priv->title_box, @@ -7551,7 +7565,7 @@ gtk_window_get_preferred_height (GtkWidget *widget, if (priv->decorated && !priv->fullscreen) { - get_decoration_borders (widget, &window_border, NULL); + get_decoration_size (widget, &window_border); if (priv->title_box != NULL) gtk_widget_get_preferred_height (priv->title_box, @@ -7602,7 +7616,7 @@ gtk_window_get_preferred_height_for_width (GtkWidget *widget, if (priv->decorated && !priv->fullscreen) { - get_decoration_borders (widget, &window_border, NULL); + get_decoration_size (widget, &window_border); if (priv->title_box != NULL) gtk_widget_get_preferred_height_for_width (priv->title_box, @@ -8827,17 +8841,14 @@ gtk_window_draw (GtkWidget *widget, GtkStyleContext *context; gboolean ret = FALSE; GtkAllocation allocation; - GtkBorder inner_border = { 0 }; - GtkBorder outer_border = { 0 }; + GtkBorder window_border; gint title_height; context = gtk_widget_get_style_context (widget); + get_decoration_size (widget, &window_border); gtk_widget_get_allocation (widget, &allocation); - if (priv->client_decorated) - get_decoration_borders (widget, &inner_border, &outer_border); - if (!gtk_widget_get_app_paintable (widget) && gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget))) { @@ -8848,25 +8859,22 @@ gtk_window_draw (GtkWidget *widget, { gtk_style_context_save (context); - gtk_style_context_add_class (context, "window-border"); + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND); + gtk_style_context_add_class (context, "window-frame"); + gtk_render_background (context, cr, - inner_border.left + outer_border.left, - inner_border.top + outer_border.top, + window_border.left, window_border.top, allocation.width - - (inner_border.left + inner_border.right + - outer_border.left + outer_border.right), + (window_border.left + window_border.right), allocation.height - - (inner_border.top + inner_border.bottom + - outer_border.top + outer_border.bottom)); + (window_border.top + window_border.bottom)); gtk_render_frame (context, cr, - outer_border.left, - outer_border.top, - allocation.width - (outer_border.left + outer_border.right), - allocation.height - (outer_border.top + outer_border.bottom)); - gtk_style_context_remove_class (context, "window-border"); - gtk_style_context_add_class (context, "window-outer-border"); - gtk_render_frame (context, cr, - 0, 0, allocation.width, allocation.height); + window_border.left, window_border.top, + allocation.width - + (window_border.left + window_border.right), + allocation.height - + (window_border.top + window_border.bottom)); + gtk_style_context_restore (context); } @@ -8874,20 +8882,23 @@ gtk_window_draw (GtkWidget *widget, title_height = gtk_widget_get_allocated_height (priv->title_box); else title_height = 0; - gtk_style_context_save (context); - gtk_style_context_add_class (context, "window-content"); + gtk_render_background (context, cr, - inner_border.left + outer_border.left, - inner_border.top + outer_border.top + - title_height, + window_border.left, + window_border.top + title_height, allocation.width - - (inner_border.left + inner_border.right + - outer_border.left + outer_border.right), + (window_border.left + window_border.right), allocation.height - - (inner_border.top + inner_border.bottom + - outer_border.top + outer_border.bottom + + (window_border.top + window_border.bottom + title_height)); - gtk_style_context_restore (context); + gtk_render_frame (context, cr, + window_border.left, + window_border.top + title_height, + allocation.width - + (window_border.left + window_border.right), + allocation.height - + (window_border.top + window_border.bottom + + title_height)); } if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw) -- 2.30.2